package com.iflytek.uoamp.notify.core.adapter;

import java.text.MessageFormat;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;

import com.alibaba.fastjson.JSON;
import com.iflytek.uoamp.common.notify.constant.ConstField;
import com.iflytek.uoamp.common.notify.enumerate.Type;
import com.iflytek.uoamp.common.notify.exception.NotifyException;
import com.iflytek.uoamp.common.notify.obj.Notification;
import com.iflytek.uoamp.common.notify.util.LogInfo;
import com.iflytek.uoamp.common.notify.util.LogbackInstance;
import com.iflytek.uoamp.notify.core.action.AbstractNotifyAction;
import com.iflytek.uoamp.notify.core.action.NotifyActionFactory;
import com.iflytek.uoamp.notify.core.dump.DumpTask;
import com.iflytek.uoamp.notify.core.protocol.ActionContext;

public class AsyncTask implements Runnable {
	
    private Queue<ActionContext> queue = null;
    
    private static final int MAX_SIZE = 65535;
    
    private static final Logger logger = LogbackInstance.getInstance().getLogger(AsyncTask.class);
    
    private static class InstanceHolder {
        private static final AsyncTask instance = new AsyncTask();
    }
    
    private AsyncTask() {
        queue = new LinkedBlockingQueue<ActionContext>(MAX_SIZE);
    }
    
    public static final AsyncTask getInstance() {
        return InstanceHolder.instance;
    }
    
    @Override
    public void run() {
        while(true) {
            if (!queue.isEmpty()) {
                try {
                    ActionContext ctx = queue.poll();
                    Notification notification = ctx.getNotification();
                    Type notificationType = Type.getType(notification.getType());
                    // ltzeng 根据Notification构造不同的NotifyAction用以处理对应的Notification
                    AbstractNotifyAction action = NotifyActionFactory.getNotifyAction(notificationType);
                    logger.info("AbstractNotifyAction is"+action);
                    LogInfo logInfo = ctx.getLogInfo();
                    action.setLogInfo(logInfo);
                    // ltzeng 关于LogInfo的错误信息和输出信息均在AbstractNotification中添加
                    
                    action.doTask(notification);
                    
                    logInfo.write();
                } catch(Exception e) {
                    logger.error(MessageFormat.format(ConstField.UNKNOWNERROR, e.getMessage()), e);
                }
            } else {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
    }
    
    public void addTask(ActionContext ctx) throws NotifyException{
        if(queue.offer(ctx) == false) {
            logger.error(MessageFormat.format(ConstField.QUEUEISFULL, ctx.getRequestPackage()));
            // ltzeng 如果通知加入队列失败，则写入dump文件，由Dump定时任务重新发送
            Notification notification = ctx.getNotification();
            DumpTask.dumpAll(notification);
        }
    }
}
